package com.bluedot.monitor;

import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.*;
import java.util.concurrent.locks.LockSupport;

/**
 * 所有monitor的抽象父类<br/>
 * 实现了Runnable接口,直接把子类对象提交至线程池则线程池会调用run方法对队列进行监听<br/>
 * monitorTaskThreadPool、parkedTomcatThreadMap、parkedPoolThreadMap为全局共享变量所以定义成静态变量,在静态代码块中进行初始化<br/>
 * monitorTaskThreadPool:monitor task运行的线程池<br/>
 * parkedTomcatThreadMap、parkedPoolThreadMap:存放被park等待返回结果的线程.只有两类线程会被park,第一类是tomcat线程池中的线程,第二类是
 * monitorTaskThreadPool线程池中执行controllerServiceQueueMonitor task和serviceMapperQueueMonitor task的线程.tomcat线程池中的
 * 线程在执行到controller层向controllerServiceQueue中发送请求处理消息后会被park住,等待从serviceControllerQueue中读取返回结果的消息,
 * parkedTomcatThreadMap用来存放tomcat线程池中被park的线程以便在serviceControllerQueueMonitor中监听到返回结果消息时将对应线程unpark
 * 读取返回结果的消息;同理,monitorTaskThreadPool线程池中的线程在执行到service层向serviceMapperQueue中发送请求处理消息后也会被park住,等待
 * 从mapperServiceQueue中读取返回结果的消息,parkedPoolThreadMap用来存放monitorTaskThreadPool线程池中被park的线程以便在
 * mapperServiceQueueMonitor中监听到返回结果消息时将对应线程unpark读取返回结果的消息
 */
public abstract class Monitor implements Runnable {

    private static final ExecutorService monitorTaskThreadPool;

    private static final Map<String, Thread> parkedTomcatThreadMap;

    private static final Map<String, Thread> parkedPoolThreadMap;

    /**
     * 初始化静态变量
     */
    static {
        parkedTomcatThreadMap = new HashMap<>();
        parkedPoolThreadMap = new HashMap<>();
        monitorTaskThreadPool = new ThreadPoolExecutor(
                4,
                4,
                1L, TimeUnit.SECONDS,
                new ArrayBlockingQueue<>(0),
                Executors.defaultThreadFactory(),
                (task, executor) -> {
                }
        );
    }

    /**
     * 将task加入到线程池中执行
     *
     * @param task 要执行的task
     */
    public static void execute(Runnable task) {
        monitorTaskThreadPool.execute(task);
    }

    /**
     * 将tomcat线程池中被park住的线程加入到parkedTomcatThreadMap中后续进行unpark
     *
     * @param key    线程的唯一标识
     * @param thread 被park住的线程
     * @return 被park住的线程
     */
    public static Thread putParkedTomcatThread(String key, Thread thread) {
        return parkedTomcatThreadMap.put(key, thread);
    }

    /**
     * unpark tomcat线程池中被park住的线程,并将其移出parkedTomcatThreadMap
     *
     * @param key 线程的唯一标识
     * @return
     */
    public static Thread unparkTomcatThread(String key) {
        synchronized (parkedTomcatThreadMap) {
            LockSupport.unpark(parkedTomcatThreadMap.get(key));
            return parkedTomcatThreadMap.remove(key);
        }
    }

    /**
     * 将parkedPoolThreadMap线程池中被park住的线程加入到map中后续进行unpark
     *
     * @param key    线程的唯一标识
     * @param thread 被park住的线程
     * @return 被park住的线程
     */
    public static Thread putParkedPoolThread(String key, Thread thread) {
        return parkedPoolThreadMap.put(key, thread);
    }

    /**
     * unpark parkedPoolThreadMap线程池中被park住的线程,并将其移出parkedPoolThreadMap
     *
     * @param key 线程的唯一标识
     * @return
     */
    public static Thread unparkPoolThread(String key) {
        synchronized (parkedPoolThreadMap) {
            LockSupport.unpark(parkedPoolThreadMap.get(key));
            return parkedPoolThreadMap.remove(key);
        }
    }
}
